module mculib.arm.rcc;


import std.traits:hasMember;
import std.bitmanip:bitfields;

import mculib.arm.utils:__Inline;
import mculib.arm.bus:CrtPriority,CrtFlag;


import mculib.chip;

static assert(__traits(getMember, Peripherals, "RCC"), "RCC not found in Peripherals");



final abstract class DRCC
{
    pragma(inline,__Inline):
    pragma(crt_constructor,CrtPriority!(CrtFlag.RCC,0))
    static this()
    {
        pragma(msg,"Clock ==>");
        pragma(msg,"<== Clock");

        //Peripherals.RCC.PLLCFGR
    }

    /**
        控制指定外设时钟使能/失能
        Params:
            name = 外设名称,字符串形式
            sel = 使能或关闭 `false`:禁用 `true`:使能
        Example:
        ---
        RCC.enablePower!("GPIOAEN")(true);
        RCC.enablePower!("GPIOAEN")(false);
        ---
    */
    static void enable(string name)(bool sel) @property 
    {
        static if(hasMember!(Peripherals.RCC.mask_APB1ENR,name))
        {
            Peripherals.RCC.APB1ENR.opDispatch!name(sel);
        }
        else static if(hasMember!(Peripherals.RCC.mask_APB2ENR,name))
        {
            Peripherals.RCC.APB2ENR.opDispatch!name(sel);
        }
        else static if(hasMember!(Peripherals.RCC.mask_AHB1ENR,name))
        {
            Peripherals.RCC.AHB1ENR.opDispatch!name(sel);
        }
        else static if(hasMember!(Peripherals.RCC.mask_AHB2ENR,name))
        {
            Peripherals.RCC.AHB2ENR.opDispatch!name(sel);
        }
        else static if(hasMember!(Peripherals.RCC.mask_APB1LPENR,name))
        {
            Peripherals.RCC.APB1LPENR.opDispatch!name(sel);
        }
        else static if(hasMember!(Peripherals.RCC.mask_APB2LPENR,name))
        {
            Peripherals.RCC.APB2LPENR.opDispatch!name(sel);
        }
        else static if(hasMember!(Peripherals.RCC.mask_AHB1LPENR,name))
        {
            Peripherals.RCC.AHB1LPENR.opDispatch!name(sel);
        }
        else static if(hasMember!(Peripherals.RCC.mask_AHB2LPENR,name))
        {
            Peripherals.RCC.AHB2LPENR.opDispatch!name(sel);
        }
        else
        {
            static assert(false,"Peripheral not found :"~name);
        }
    }
    /**
        查询外设时钟使能状态,支持低功耗时钟使能查询
        Params:
            name = 外设名称,字符串形式
        Return:
            使能状态, `true`:使能 `false`:失能
        Example:
        ---
        bool en = RCC.isPowerEnabled!("GPIOAEN");
        ---
    */
    static bool isEnabled(string name)() @property 
    {
		static if(hasMember!(Peripherals.RCC.mask_APB1ENR,name))
		{
			return Peripherals.RCC.APB1ENR.opDispatch!name();
		}
		else static if(hasMember!(Peripherals.RCC.mask_APB2ENR,name))
		{
			return Peripherals.RCC.APB2ENR.opDispatch!name();
		}
		else static if(hasMember!(Peripherals.RCC.mask_AHB1ENR,name))
		{
			return Peripherals.RCC.AHB1ENR.opDispatch!name();
		}
		else static if(hasMember!(Peripherals.RCC.mask_AHB2ENR,name))
		{
			return Peripherals.RCC.AHB2ENR.opDispatch!name();
		}
		else static if(hasMember!(Peripherals.RCC.mask_APB1LPENR,name))
		{
			return Peripherals.RCC.APB1LPENR.opDispatch!name();
		}
		else static if(hasMember!(Peripherals.RCC.mask_APB2LPENR,name))
		{
			return Peripherals.RCC.APB2LPENR.opDispatch!name();
		}
		else static if(hasMember!(Peripherals.RCC.mask_AHB1LPENR,name))
		{
			return Peripherals.RCC.AHB1LPENR.opDispatch!name();
		}
		else static if(hasMember!(Peripherals.RCC.mask_AHB2LPENR,name))
		{
			return Peripherals.RCC.AHB2LPENR.opDispatch!name();
		}
		else
		{
            static assert(false,"Peripheral not found :"~name);
        }
    }

    /**
        获取时钟设置目标频率
        Params:
            name = 外设名称,字符串形式
        Return:
            时钟设置目标频率, 单位:Hz
        Example:
        ---
        uint freq = RCC.getClockFreq!("SYSCLK");
        ---
    */

    /**
        获取时钟参数
    */
    static ClockConfig getClockConfig() @property 
    {
        ClockConfig config;
        
        return config;
    }
}

/// 时钟设置结构
struct ClockConfig
{
    /*
    union
    {
        uint value;
        mixin(bitfields!(
            uint, "x",    2,
            int,  "y",    3,
            uint, "z",    2,
            bool, "flag", 1));
    }
    */
}

/// 系统时钟源选择
enum SysClockSource
{
    HSI = 0,        ///< 内置高速时钟(HSI)
    HSE = 1,        ///< 外部高速时钟(HSE)
    PLL = 2,        ///< 主时钟(PLL)
}
/// APB 分频表
enum APBDivider
{
    DIV1 = 0,       ///< 不分频
    DIV2 = 0b100,   ///< 除以 2
    DIV4 = 0b101,   ///< 除以 4
    DIV8 = 0b110,   ///< 除以 8
    DIV16 = 0b111,  ///< 除以 16
}
/// AHB 分频表
enum AHBDivider
{
    DIV1 = 0,       ///< 不分频
    DIV2 = 0b1000,  ///< 除以 2
    DIV4 = 0b1001,  ///< 除以 4
    DIV8 = 0b1010,  ///< 除以 8
    DIV16 = 0b1011, ///< 除以 16
    DIV64 = 0b1100, ///< 除以 64
    DIV128 = 0b1101, ///< 除以 128
    DIV256 = 0b1110, ///< 除以 256
    DIV512 = 0b1111, ///< 除以 512
}




import mculib.arm.bus;
private 
//pragma(crt_constructor,CrtPriority!(CrtFlag.RCC,0))
static aa1(V)()
{
    //import config;
    pragma(msg,"Clock ==>");

    pragma(msg,"<== Clock");
}

//pragma(crt_constructor,CrtPriority!(CrtFlag.RCC,0))

//enum inia =  aa1!int;


/**
    初始化时钟设置
    Example:
    ---
    enum Conf = ClockConfig();
    alias InitA = InitClock!Conf;
    ---
*/
template InitClock( ClockConfig conf )
{
    pragma(crt_constructor,CrtPriority!(CrtFlag.RCC,0))
    static this()
    {
        pragma(msg,"Clock ==>");

        pragma(msg,"<== Clock");
    }
}

//alias ma1!int a1;
